package com.sye.threadmodule.threadutil;

import java.util.concurrent.CountDownLatch;

/**
 * CountDownLatch使用案例
 * 使用:
 *     final CountDownLatch countDown = new CountDownLatch(2)实例化对象，当前参数传递的是2，所以当第一个
 *     线程调用countDown.await()后进行阻塞，当后面两个线程都调用了countDown.countDown()后，被阻塞的线程才
 *     会继续执行，如果没有达到2个线程调用countDown的方法，那么线程会一直阻塞。
 * 应用场景:
 *     监控连接是否成功，例如:连接zk:一开始连接，连接完迅速调用zk的API这样会有问题，所以要启动一个
 * 	   线程监控是否连接成功，成功后在调用zk的API。类似于wait和notify的效果，但是CountDownLatch能控制多个线程
 * 	   而且没有延迟，wait和notify有延迟的原因就是notify是不释放锁，必须等当前锁的代码执行完毕
 */
public class UseCountDownLatch {

	public static void main(String[] args) {
		
		final CountDownLatch countDown = new CountDownLatch(2);
		
		Thread t1 = new Thread(new Runnable() {
			@Override
			public void run() {
				try {
					System.out.println("进入线程t1" + "等待其他线程处理完成...");
					countDown.await();
					System.out.println("t1线程继续执行...");
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		},"t1");
		
		Thread t2 = new Thread(new Runnable() {
			@Override
			public void run() {
				try {
					System.out.println("t2线程进行初始化操作...");
					Thread.sleep(3000);
					System.out.println("t2线程初始化完毕，通知t1线程继续...");
					countDown.countDown();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		});
		Thread t3 = new Thread(new Runnable() {
			@Override
			public void run() {
				try {
					System.out.println("t3线程进行初始化操作...");
					Thread.sleep(4000);
					System.out.println("t3线程初始化完毕，通知t1线程继续...");
					countDown.countDown();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		});
		
		t1.start();
		t2.start();
		t3.start();
		
		
		
	}
}
